package com.kylin.common.datascope.aspect;

import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.kylin.common.datascope.context.DataScopeHolder;
import lombok.SneakyThrows;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.io.StringReader;
import java.sql.SQLException;

/**
 * 数据权限拦截器
 * @author wuhao
 * @version 1.0 - 2023/3/29
 */
public class DataScopeInterceptor implements InnerInterceptor {

    @SneakyThrows
    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {

        // 判断是否有数据权限
        if(StringUtils.isNotBlank(DataScopeHolder.getContext())) {
            String dataScopeSql = DataScopeHolder.getContext();
            CCJSqlParserManager parserManager = new CCJSqlParserManager();
            Select select = (Select) parserManager.parse(new StringReader(boundSql.getSql()));
            PlainSelect plain = (PlainSelect) select.getSelectBody();

            if (plain.getWhere() == null) {
                plain.setWhere(CCJSqlParserUtil.parseCondExpression(dataScopeSql));
            } else {
                plain.setWhere(new AndExpression(plain.getWhere(), CCJSqlParserUtil.parseCondExpression(dataScopeSql)));
            }

            // 修改原始的sql
            PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql);
            mpBoundSql.sql(select.toString());
        } else {
            InnerInterceptor.super.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        }

    }
}
